﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Entropy3D.Graphics
{
    /** GraphicsObject.cs **
     * Represents a single, drawable object (a model).
     */
    public class GraphicsObject
    {

        private bool    drawOnCall = true;    // Indicates whether or not to draw this object on the next call.
        private Effect effect;

        private Transform transform;
        public Transform Transform
        {
            get { return transform; }
        }

        protected string name = "NoName";
        public string Name
        {
            get { return name; }
        }

        protected Model model;
        public Model Model
        {
            get { return model; }
        }

        private List<Texture2D> textures;
        
        public GraphicsObject()
        {
            Pool.AddObject(this);
        }

        public GraphicsObject(string name)
        {
            this.name = name;
            Pool.AddObject(this);
        }

        public GraphicsObject(string name, Model model, Effect effect)
        {
            this.name = name;
            this.effect = effect;
            textures = new List<Texture2D>();
            SetModel(model);
            Pool.AddObject(this);
        }

        public void SetModel(Model model)
        {
            this.model = model;

            if (effect != null)
            {
                foreach (ModelMesh mesh in model.Meshes)
                {
                    
                    foreach (ModelMeshPart meshPart in mesh.MeshParts)
                    {
                        // textures.Add(((BasicEffect)meshPart.Effect).Texture);
                        meshPart.Effect = effect.Clone();
                    }
                }
            }

            transform = new Transform();
        }

        public void SetEffect(Effect e)
        {
            this.effect = e;
        }

        public void SetColor(Color col)
        {
            this.color = col;
        }

        private Color color = Color.White;

        public void Update(GameTime gameTime)
        {

        }

        public void Prepare()
        {
            drawOnCall = true;
            // TODO: check if this object should be drawn
        }

        public void Draw(Matrix view, Matrix projection)
        {
            if (!drawOnCall) return;
            if (effect == null) return;

            Matrix[] modelTransforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(modelTransforms);
            foreach (ModelMesh mesh in model.Meshes)
            {
                

                
                foreach (Effect currentEffect in mesh.Effects)
                {
                    currentEffect.CurrentTechnique = currentEffect.Techniques["Colored"];
                    currentEffect.Parameters["xWorld"].SetValue(modelTransforms[mesh.ParentBone.Index] * Transform.TransformMatrix);
                    currentEffect.Parameters["xView"].SetValue(view);
                    currentEffect.Parameters["xProjection"].SetValue(projection);
                    currentEffect.Parameters["xEnableLighting"].SetValue(true);
                    // currentEffect.Parameters["xColor"].SetValue(color.ToVector4());

                }
                
                // Console.WriteLine("Effects count: " + mesh.Effects.Count);
                /*
                foreach (BasicEffect be in mesh.Effects)
                {
                    be.EnableDefaultLighting();
                    be.DiffuseColor = new Vector3(1f, 0f, 0f);
                    be.View = view;
                    be.Projection = projection;

                    be.World = Transform.TransformMatrix;
                }
                */

                mesh.Draw();
            }
        }
    }
}
